package fons.model.ontology;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import fons.model.ontology.interfaces.DecisionMaker;
import fons.model.ontology.requirement.Requirement;

public abstract class AbstractView implements RequirementListener, DecisionMaker {

	protected final String name;
	private ViewModel viewModel;
	
	public AbstractView (String name) {
		this.name = name;
	}

	public static String[] selectDimensions(Set<Dimension> dimensions) {
		Set<String> result = Sets.newTreeSet();
		for (Dimension d: dimensions) {
				result.add(d.getName());
		}
	
		return result.toArray(new String[0]);
	}

	public abstract void constrain(Map<String, Set<Dimension>> dimensions);

	public final void setViewModel(ViewModel viewModel) {
		this.viewModel = viewModel;
		viewModel.getContext().addRequirementListener(this);
	}

	public final ViewModel getViewModel() {
		return this.viewModel;
	}

	public final Context getContext() {
		return this.viewModel.getContext();
	}

	public static class SelectionHelper implements Comparable<SelectionHelper> {
		public Dimension dimension;
		public Set<Dimension> filter;
		
		@Override
		public int compareTo(SelectionHelper o) {
			return Dimension.COMPARE_BY_NAME.compare(this.dimension, o.dimension);
		}
	}

	public static SelectionHelper[] selectDimensions(Set<Dimension> dimensions, List<Set<Dimension>> filters) {
		List<SelectionHelper> result = Lists.newArrayListWithCapacity(dimensions.size() * filters.size());
		for (Dimension d: dimensions) {
			for (Set<Dimension> filter: filters) {
				SelectionHelper helper = new SelectionHelper();
				helper.dimension = d;
				helper.filter = filter; 
				result.add(helper);
			}
		}
		Collections.sort(result);
		return result.toArray(new SelectionHelper[0]);
	}

	@Override
	public void missingRequirement(Requirement requirement) {
		this.getContext().provide(requirement);
	}

	@Override
	public SelectionDefinition chooseSelection(final Collection<SelectionDefinition> possibleMatches, final Set<Dimension> currentSelection) {
		return possibleMatches.iterator().next();
	}

	public String getName() {
		return this.name;
	}

	public abstract void update();

}